/*
 *  PestExterm.cpp
 *  
 *
 *  Created by Daniel Condon on 25/07/12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

#include <GLUT/glut.h>
#include <OpenGL/glu.h>
#include <OpenGL/gl.h>
#include <OpenGL/OpenGL.h>

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>

#include "Renderer.cpp"

using namespace std;

int VIEW_DISTANCE;
const int WINDOW_SIZE_X = 600;
const int WINDOW_SIZE_Y = 600;

const int seedCellx = 25;
const int seedCelly = 25;

bool DEBUG;

int selectedCellX, selectedCellY;

CellularAutomation* cellMatrix;
IBMController* IBMMonitor;
Renderer* renderer;

Creature creatures;

bool PAUSED, CellMode;

void convertMouseCoord(int x, int y){
	mouseXObjectSpace = (x - (WINDOW_SIZE_X/2.0f)) / (WINDOW_SIZE_X/2.0f) * (VIEW_DISTANCE/2.0f);
	mouseYObjectSpace = (-y + (WINDOW_SIZE_Y/2.0f)) / (WINDOW_SIZE_Y/2.0f) * (VIEW_DISTANCE/2.0f);
}

void Init(){
	renderer->Init();
}

void display(){
	renderer->display();
}

void reshape(int w, int h){
	renderer->reshape(w,h);
}

void SwapToIBMMode(){
	IBMMonitor = new IBMController(cellMatrix->getCellCurrent(selectedCellX, selectedCellY)/5);
	renderer->InitIBM(IBMMonitor);
	renderer->SwapMode(1);
	CellMode = false;
}

void SwapToCellMode(){
	renderer->SwapMode(0);
	CellMode = true;
}

void KeyboardController(GLubyte key, GLint x, GLint y){
	string put;
	switch ((char)key) {
		case 27:
			exit(1);
			break;
		case 'd':
			DEBUG = !DEBUG;
			renderer->ToggleDebug(DEBUG);
			break;
		case 'c':
			if (!CellMode) {
				SwapToCellMode();
			}
			break;
		case 'i':
			if (!CellMode) {
				IBMMonitor->getCreature(0)->giveVirus();
			}
			break;
		case 's':
			if (CellMode) {
				cellMatrix->seedCell(seedCellx,seedCelly,50);
			}
			break;
		case 'p':
			PAUSED = !PAUSED;
			break;
		case 'b':
			cout << "Entering barrier placement mode." << endl;
			if (!PAUSED) {
				PAUSED = !PAUSED;
			}
			cout << "Input sides to barricade: " << endl;
			cin >> put;
			if (put.length() > 0) {
				for (int i = 0; i < put.length(); i++) {
					switch (put.at(i)) {
						case 'a':
							cellMatrix->getCell(mouseXObjectSpace, mouseYObjectSpace)->PlaceBarrier(0);
							break;
						case 'b':
							cellMatrix->getCell(mouseXObjectSpace, mouseYObjectSpace)->PlaceBarrier(1);
							break;
						case 'c':
							cellMatrix->getCell(mouseXObjectSpace, mouseYObjectSpace)->PlaceBarrier(2);
							break;
						case 'd':
							cellMatrix->getCell(mouseXObjectSpace, mouseYObjectSpace)->PlaceBarrier(3);
							break;
						default:
							break;
					}
				}
			}
			break;
		default:
			break;
	}
}

void Clip(){
	mouseXObjectSpace = (int)((mouseXObjectSpace + 250)/10);
	mouseYObjectSpace = (int)((mouseYObjectSpace + 250)/10);
	selectedCellX = mouseXObjectSpace;
	selectedCellY = mouseYObjectSpace;
}

void mouseInput(int button, int state, int x, int y){
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		if(CellMode){
			convertMouseCoord(x, y);
			VIEW_DISTANCE = 500;
			Clip();
			cout << "Pop of selected zone: " << cellMatrix->getCell(mouseXObjectSpace, mouseYObjectSpace)->getCellCurrent() << endl;
			renderer->Click(mouseXObjectSpace, mouseYObjectSpace);
			SwapToIBMMode();
		}
	}else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
		SwapToCellMode();
	}
	
}

void LogicLoop(int value){
	if (!PAUSED) {
		if (CellMode) {
			cellMatrix->Cycle();
		}else {
			IBMMonitor->Cycle();
		}
	}
	glutPostRedisplay();
	if (CellMode) {
		glutTimerFunc(250, LogicLoop, 250);
	}else{
		glutTimerFunc(15, LogicLoop, 15);
	}
	
}

void SafeClose(){
	//delete cellMatrix;
	//delete IBMMonitor;
	//delete Renderer;
}

int main(int argc, char** argv){
	srand(time(NULL));
	CellMode = true;
	DEBUG = false;
	VIEW_DISTANCE = 500;
	renderer = new Renderer;
	cellMatrix = new CellularAutomation(MatrixColumns, MatrixRows, creatures);
	
	renderer->InitCellMatrix(cellMatrix);
	
	glutInitWindowSize(WINDOW_SIZE_X, WINDOW_SIZE_Y);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	glutCreateWindow("Pest Exterminator");
	
	Init();
	glutKeyboardFunc(KeyboardController);
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMouseFunc(mouseInput);
	
	LogicLoop(15);
	glutMainLoop();
	
	SafeClose();
	return 0;
}

